﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;
using System.Net;
using System.Net.Sockets;
using System.IO;

namespace LippeMartinProject4
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            InitTicTacToe();
        }

        private delegate string myReadlineDel();
        private delegate void myDisconnect();
        private delegate void myLoad(string a);

        private bool[,] moves = new bool[3, 3];
        private string piece = "i";
        TcpClient tcp;
        IPAddress ip;
        IPEndPoint ipe;
        int port;
        StreamWriter sw;
        StreamReader sr;
        NetworkStream ns;
        bool joined = false;
        bool myTurn = false;
        int foreignx = 0;
        int foreigny = 0;
        PictureBox[,] pictures = new PictureBox[3,3];

        public void InitTicTacToe()
        {
            pictures[0, 0] = box00;
            pictures[0, 1] = box01;
            pictures[0, 2] = box02;
            pictures[1, 0] = box10;
            pictures[1, 1] = box11;
            pictures[1, 2] = box12;
            pictures[2, 0] = box20;
            pictures[2, 1] = box21;
            pictures[2, 2] = box22;
            pictures[0, 0].SizeMode = PictureBoxSizeMode.StretchImage;
            pictures[0, 1].SizeMode = PictureBoxSizeMode.StretchImage;
            pictures[0, 2].SizeMode = PictureBoxSizeMode.StretchImage;
            pictures[1, 0].SizeMode = PictureBoxSizeMode.StretchImage;
            pictures[1, 1].SizeMode = PictureBoxSizeMode.StretchImage;
            pictures[1, 2].SizeMode = PictureBoxSizeMode.StretchImage;
            pictures[2, 0].SizeMode = PictureBoxSizeMode.StretchImage;
            pictures[2, 1].SizeMode = PictureBoxSizeMode.StretchImage;
            pictures[2, 2].SizeMode = PictureBoxSizeMode.StretchImage;
            pictures[0, 0].Load("empty.png");
            pictures[0, 1].Load("empty.png");
            pictures[0, 2].Load("empty.png");
            pictures[1, 0].Load("empty.png");
            pictures[1, 1].Load("empty.png");
            pictures[1, 2].Load("empty.png");
            pictures[2, 0].Load("empty.png");
            pictures[2, 1].Load("empty.png");
            pictures[2, 2].Load("empty.png");
            moves = new bool[3, 3];
        }

        private void joinThread()
        {
            myDisconnect ml = new myDisconnect(InitTicTacToe);
            Invoke(ml);
            try
            {
                ip = IPAddress.Parse(ipText.Text);
                port = Int32.Parse(portText.Text);
                ipe = new IPEndPoint(ip, port);
                tcp = new TcpClient();
                tcp.Connect(ipe);
                ns = tcp.GetStream();
                sw = new StreamWriter(ns);
                sr = new StreamReader(ns);
                sw.WriteLine("request = join");
                sw.Flush();
                string reply = sr.ReadLine();
                if (reply == "join = rejected")
                {
                    //do something?
                    joined = false;
                    myDisconnect md = new myDisconnect(toggleJoin);
                    Invoke(md);
                }
                else
                {
                    piece = reply.Substring(7);
                    joined = true;
                    Thread t = new Thread(new ThreadStart(Listen));
                    t.IsBackground = true;
                    t.Start();
                }
            }
            catch (Exception e)
            {
                MessageBox.Show(e.Message);
            }
        }

        #region buttons

        private void box00_Click(object sender, EventArgs e)
        {
            move(0, 0);
        }
        private void box01_Click(object sender, EventArgs e)
        {
            move(0, 1);
        }
        private void box02_Click(object sender, EventArgs e)
        {
            move(0, 2);
        }
        private void box10_Click(object sender, EventArgs e)
        {
            move(1, 0);
        }
        private void box11_Click(object sender, EventArgs e)
        {
            move(1, 1);
        }
        private void box12_Click(object sender, EventArgs e)
        {
            move(1, 2);
        }
        private void box20_Click(object sender, EventArgs e)
        {
            move(2, 0);
        }
        private void box21_Click(object sender, EventArgs e)
        {
            move(2, 1);
        }
        private void box22_Click(object sender, EventArgs e)
        {
            move(2, 2);
        }


        private void hostButton_Click(object sender, EventArgs e)
        {
            box00.Dispose();
            box01.Dispose();
            box02.Dispose();
            box10.Dispose();
            box11.Dispose();
            box12.Dispose();
            box20.Dispose();
            box21.Dispose();
            box22.Dispose();
        }

        private void joinButton_Click(object sender, EventArgs e)
        {
            Thread t = new Thread(new ThreadStart(joinThread));
            t.IsBackground = true;
            t.Start();
            joinButton.Enabled = false;
        }

        #endregion buttons

        private void move(int x, int y)
        {
            if (joined)
            {
                if (myTurn)
                {
                    if (moves[x, y] == true)
                    {
                        MessageBox.Show("That space has already been used.");
                    }
                    else
                    {
                        //send to server
                        sw.WriteLine("xindex = " + x);
                        sw.Flush();
                        sw.WriteLine("yindex = " + y);
                        sw.Flush();
                        sw.WriteLine("char = " + piece);
                        sw.Flush();
                        myTurn = false;
                    }
                }
                else
                {
                    //not your turn
                    MessageBox.Show("You must wait your turn");
                }
            }
            else
            {
                //not connected
                MessageBox.Show("You are not in a game.");
            }
        }

        private void Listen()
        {
            string reply = "";
            StreamReader listenw = new StreamReader(ns);
            string[] sundered = new string[0];
            char[] delim = {' '};
            while (true)
            {
                reply = listenw.ReadLine();
                //myReadlineDel rd = new myReadlineDel(sr.ReadLine);
                //reply = (string)Invoke(rd);
                sundered = reply.Split(delim, StringSplitOptions.RemoveEmptyEntries);
                if (sundered[0] == "join")
                {
                    if (sundered[2] == "joined") joined = true;
                    else joined = false;
                }
                else if (sundered[0] == "xindex")
                {
                    foreignx = Int32.Parse(sundered[2]);
                }
                else if (sundered[0] == "yindex")
                {
                    foreigny = Int32.Parse(sundered[2]);
                }
                else if (sundered[0] == "char")
                {
                    moves[foreignx, foreigny] = true;
                    myLoad ml = new myLoad(pictures[foreignx, foreigny].Load);
                    if (sundered[2] == "x")
                    {
                        //pictures[foreignx, foreigny].Load("X_icon.png");
                        Invoke (ml, "X_icon.png");
                    }
                    else
                    {
                        //pictures[foreignx, foreigny].Load("O_icon.png");
                        Invoke (ml, "O_icon.png");
                    }
                }
                else if (sundered[0] == "turn")
                {
                    if (sundered[2] == piece)
                    {
                        myTurn = true;
                    }
                    else myTurn = false;
                }
                else if (sundered[0] == "outcome")
                {
                    if (sundered[2] == "" + piece)
                    {
                        //you win
                        MessageBox.Show("You win!");
                    }
                    else if (sundered[2] == "t")
                    {
                        //tie game
                        MessageBox.Show("Tie game!");
                    }
                    else
                    {
                        //you lose
                        MessageBox.Show("You lose.");
                    }
                    //disconnect
                    joined = false;
                    myTurn = false;
                    myDisconnect md = new myDisconnect(tcp.Close);
                    Invoke(md);
                    myDisconnect ml = new myDisconnect(InitTicTacToe);
                    Invoke(ml);
                    myDisconnect md2 = new myDisconnect(toggleJoin);
                    Invoke(md2);
                    myLoad ml2 = new myLoad(setPiece);
                    Invoke(ml2, "");
                    return;
                }
                else if (sundered[0] == "disconnect")
                {
                    if (sundered[2] == "yes")
                    {
                        //disconnect
                        joined = false;
                        myTurn = false;
                        myDisconnect md = new myDisconnect(tcp.Close);
                        Invoke(md);
                        myDisconnect ml = new myDisconnect(InitTicTacToe);
                        Invoke(ml);
                        myDisconnect md2 = new myDisconnect(toggleJoin);
                        Invoke(md2);
                        myLoad ml2 = new myLoad(setPiece);
                        Invoke(ml2, "");
                        return;
                    }
                }
                else if (sundered[0] == "piece")
                {
                    myLoad ml = new myLoad(setPiece);
                    Invoke(ml, sundered[2]);
                    //piece = sundered[2];
                    //pieceBox.Text = sundered[2];
                }
            }
        }

        private void setPiece(string a)
        {
            piece = a;
            pieceBox.Text = a;
        }

        private void toggleJoin()
        {
            joinButton.Enabled = !joinButton.Enabled;
        }
    }
}
